using System;
using System.Collections.Generic;
using Gj.Galaxy.Logic;
using UnityEngine;

namespace Gj
{
    public class BaseGameSpace : MonoBehaviour, GameListener, GameBeforeListener, GameReadyListener, BroadcastListener,
        TimeListener
    {
        public BaseUISpace UiSpace;
        private readonly List<GamePlugin> gamePlugins = new();
        private readonly List<GameService> gameServices = new();

        private void Awake()
        {
        }

        private void Start()
        {
        }

        public void Init()
        {
            OnInit();
        }

        private void Update()
        {
            OnUpdate();
        }

        private void LateUpdate()
        {
            foreach (var plugin in gamePlugins)
            {
                plugin.OnUpdate();
            }

            foreach (var service in gameServices)
            {
                service.OnUpdate();
            }
            OnLateUpdate();
        }

        private void OnDestroy()
        {
            foreach (var plugin in gamePlugins) plugin.OnDestroy();
            foreach (var service in gameServices) service.OnDestroy();
        }

        public void OnBroadcast(GamePlayer player, byte code, Vector3 position, StreamReader reader)
        {
            LogTools.Log("OnBroadcast");
            foreach (var plugin in gamePlugins) plugin.OnBroadcast(player, code, position, reader);
        }

        public void OnSwitchArea()
        {
            LogTools.Log("OnSwitchArea");
            foreach (var plugin in gamePlugins) plugin.OnSwitchArea();
        }

        public virtual void OnInstance(int prefabIndex, byte relation, GamePlayer player, Vector3 position,
            bool isLocal, NetworkEsse master, Action<InitSyncListener> cb)
        {
            LogTools.Log("OnInstance");
            foreach (var plugin in gamePlugins)
                plugin.OnInstance(prefabIndex, relation, player, position, isLocal, master, cb);
        }

        public virtual void OnDestroy(NetworkEsse instance, GamePlayer player)
        {
            LogTools.Log("OnDestroyInstance");
            foreach (var plugin in gamePlugins) plugin.OnDestroy(instance, player);
        }

        public void OnEnterRoom(bool first)
        {
            LogTools.Log("OnEnter:" + first);
            AnalyticsManager.Event("enterRoom", new Dictionary<string, object> { { "first", first } });
            foreach (var plugin in gamePlugins) plugin.OnEnterRoom(first);
        }

        public void OnPlayerJoin(GamePlayer player)
        {
            LogTools.Log("OnPlayerJoin");
            foreach (var plugin in gamePlugins) plugin.OnPlayerJoin(player);
        }

        public void OnPlayerLeave(GamePlayer player)
        {
            LogTools.Log("OnPlayerLeave");
            foreach (var plugin in gamePlugins) plugin.OnPlayerLeave(player);
        }

        public void OnPlayerRejoin(GamePlayer player)
        {
            LogTools.Log("OnPlayerRejoin");
            foreach (var plugin in gamePlugins) plugin.OnPlayerRejoin(player);
        }

        public void OnProcessRoom(object[] data)
        {
            LogTools.Log("OnProcess");
            foreach (var plugin in gamePlugins) plugin.OnProcessRoom(data);
        }

        public void OnInitGame()
        {
            LogTools.Log("OnInitGame");
            AnalyticsManager.Event("initGame");
            foreach (var plugin in gamePlugins) plugin.OnInitGame();
        }

        public void OnStart()
        {
            LogTools.Log("OnStart");
            AnalyticsManager.Event("startGame");
            foreach (var plugin in gamePlugins) plugin.OnStart();
        }

        public void OnFinish(object result)
        {
            LogTools.Log("OnFinish");
            AnalyticsManager.Event("finishGame");
            foreach (var plugin in gamePlugins) plugin.OnFinish(result);
        }

        public void OnFailConnect()
        {
            LogTools.Log("OnFailConnect");
            foreach (var plugin in gamePlugins) plugin.OnFailConnect();
        }

        public void OnReadyPlayer(GamePlayer player)
        {
            LogTools.Log("OnReadyPlayer");
            foreach (var plugin in gamePlugins) plugin.OnReadyPlayer(player);
        }

        public void OnReady()
        {
            LogTools.Log("OnReady");
            foreach (var plugin in gamePlugins) plugin.OnReady();
        }

        public void OnReadyAll()
        {
            LogTools.Log("OnReadyAll");
            AnalyticsManager.Event("readyAllGame");
            foreach (var plugin in gamePlugins) plugin.OnReadyAll();
        }

        public void OnTimeMove(int startTime, int endTime, StreamReader reader, Vector3[] positions, int index,
            Vector3 middlePosition)
        {
            LogTools.Log("OnTimeMove");
            foreach (var plugin in gamePlugins)
                plugin.OnTimeMove(startTime, endTime, reader, positions, index, middlePosition);
        }

        public void OnTimeProcess(int startTime, int endTime, StreamReader reader)
        {
            LogTools.Log("OnTimeProcess");
            foreach (var plugin in gamePlugins) plugin.OnTimeProcess(startTime, endTime, reader);
        }

        protected virtual void OnInit()
        {
        }

        protected void RegisterPlugin(GamePlugin plugin)
        {
            // 同一个插件只用注册一次
            if (gamePlugins.Contains(plugin)) return;
            plugin.OnInit(this);
            foreach (var service in plugin.GetRequireService()) RegisterService(service);
            gamePlugins.Add(plugin);
        }

        protected void RegisterService(GameService service)
        {
            // 同一个服务只用注册一次
            if (gameServices.Contains(service)) return;
            service.OnInit();
            gameServices.Add(service);
        }

        protected virtual void OnUpdate()
        {
        }

        protected virtual void OnLateUpdate()
        {
        }
    }
}